#include "time_wheel.h"

TimeWheel::TimeWheel(uint32_t scales,
                     uint32_t scale_unit_ms,
                     const std::string& name )
    : m_name(name)
    , m_current_index(0)
    , m_scales(scales)
    , m_scale_uint_ms(scale_unit_ms)
    , m_slots(scales)
    , m_less_level_tw(nullptr)
    , m_greater_level_tw(nullptr)
{

}

int64_t TimeWheel::getCurrentTime() const
{
    int64_t time = m_current_index * m_scale_uint_ms;
    if (m_less_level_tw != nullptr)
    {
        time += m_less_level_tw->getCurrentTime();
    }

    return time;
}

void TimeWheel::addTime(TimerPtr pTimer)
{
    int64_t less_tw_time = 0;
    if (m_less_level_tw != nullptr)
    {
        less_tw_time = m_less_level_tw->getCurrentTime();
    }
    int64_t diff = pTimer->getWhenMs() + less_tw_time - getCurrentTime();
    if (diff >= m_scale_uint_ms)
    {
        size_t n = (m_current_index + diff / m_scale_uint_ms) & m_scales;
        m_slots[n].push_back(pTimer);
        return;
    }

    if(m_less_level_tw != nullptr)
    {
        m_less_level_tw->addTime(pTimer);
    }

    m_slots[m_current_index].push_back(pTimer);
}

void TimeWheel::increase()
{
    ++m_current_index;
    if (m_current_index < m_scales)
    {
        return;
    }

    m_current_index = m_current_index % m_scales;
    if (m_greater_level_tw != nullptr)
    {
        m_greater_level_tw->increase();
        std::list<TimerPtr> slot = m_greater_level_tw->getAndClearCurrentSlot();
        for (TimerPtr& timer : slot)
        {
            addTime(timer);
        }
    }
}

std::list<TimerPtr> TimeWheel::getAndClearCurrentSlot()
{
    std::list<TimerPtr> slot;
    slot = std::move(m_slots[m_current_index]);
    return slot;
}






















